package br.kanban.view.mb;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;

import br.kanban.core.busines.HistoricoBO;
import br.kanban.core.busines.TarefaBO;
import br.kanban.core.persistence.Historico;
import br.kanban.core.persistence.Historico.TipoHistorico;
import br.kanban.core.persistence.Sprint;
import br.kanban.core.persistence.Tarefa;
import br.kanban.core.persistence.Tarefa.StatusTarefa;
import br.kanban.core.persistence.Usuario;

@Named
@ApplicationScoped
public class QuadroService implements Serializable {

	private static final long serialVersionUID = 1L;
	
	private List<Tarefa> tarefasAberta;
	private List<Tarefa> tarefasPendente;
	private List<Tarefa> tarefasConferencia;
	
	@Inject
	private HistoricoBO historicoBO;
	
	@Inject
	private TarefaBO tarefaBO;
	
	@PostConstruct
	public void init(){
		Tarefa filtro = new Tarefa();
		filtro.setStatus(StatusTarefa.ABERTO);
		tarefasAberta = tarefaBO.pesquisar(filtro);

		filtro.setStatus(StatusTarefa.ANDAMENTO);
		tarefasPendente = tarefaBO.pesquisar(filtro);
		
		filtro.setStatus(StatusTarefa.CONFERENCIA);
		tarefasConferencia = tarefaBO.pesquisar(filtro);
	}
	
	public synchronized void delegar(Usuario usuario, Tarefa tarefa){
		//Verifica se usuario pertence a Sprint
		if(tarefa.getSprint().getUsuarios().contains(usuario)){
			//verifica se usuario não tem tarefas pendente.
			if(isPodeDelegar(usuario)){
				if(tarefa.getStatus() == StatusTarefa.ABERTO){
					tarefasAberta.remove(tarefa);
					tarefa.setStatus(StatusTarefa.ANDAMENTO);
					tarefa.setUsuario(usuario);
					tarefaBO.update(tarefa);
					tarefasPendente.add(tarefa);
				}else{
					tarefa.setUsuario(usuario);
					tarefaBO.update(tarefa);					
				}
				
				//Cria um histórico da tarefa
				Historico historico = new Historico();
				historico.setDescricao("Delegou para si a tarefa");
				historico.setTipo(TipoHistorico.DELEGAR);
				historico.setUsuario(usuario);
				historico.setTarefa(tarefa);
				historicoBO.insert(historico);
				
			}else{//Se usuario ja esta executando uma tarefa
				FacesContext.getCurrentInstance().addMessage(null, 
						new FacesMessage(FacesMessage.SEVERITY_ERROR, "Você já possui tarefa em andamento.", "")); 
			}
		}else{//se Usuario nao pertence a Sprint
			FacesContext.getCurrentInstance().addMessage(null, 
					new FacesMessage(FacesMessage.SEVERITY_ERROR, "Você não tem permissão para executar esta tarefa.", "")); 			
		}
		
	}
	
	
	public synchronized void reabrir(Usuario usuarioOld, Tarefa tarefa){
		tarefasConferencia.remove(tarefa);
		tarefa.setStatus(StatusTarefa.ANDAMENTO);
		tarefa.setUsuario(usuarioOld);
		tarefaBO.update(tarefa);
		tarefasPendente.add(tarefa);
		
		//Cria um histórico da tarefa
		Historico historico = new Historico();
		historico.setDescricao("Deve refazer a tarefa");
		historico.setTipo(TipoHistorico.RETRABALHO);
		historico.setUsuario(usuarioOld);
		historico.setTarefa(tarefa);
		historicoBO.insert(historico);
	}
	
	public void finalizar(Tarefa tarefa, Usuario usuario){
		if(tarefa.getStatus() == StatusTarefa.ANDAMENTO){
			tarefasPendente.remove(tarefa);
			tarefasConferencia.add(tarefa);
			tarefa.setUsuario(null);
			tarefa.setStatus(StatusTarefa.CONFERENCIA);
		}else{
			tarefasConferencia.remove(tarefa);
			tarefa.setStatus(StatusTarefa.FECHADO);			
		}
		tarefaBO.update(tarefa);

		//Cria um histórico da tarefa
		Historico historico = new Historico();
		historico.setDescricao("Finalizou a tarefa");
		historico.setTipo(TipoHistorico.FINALIZA);
		historico.setUsuario(usuario);
		historico.setTarefa(tarefa);
		historicoBO.insert(historico);
	}
	
	public void novo(final Tarefa tarefa){
		tarefasAberta.add(tarefa);
	}
	
	public void update(final Tarefa tarefa){
		if(tarefasAberta.contains(tarefa)){
			tarefasAberta.set(tarefasAberta.indexOf(tarefa), tarefa);
		}else if(tarefasPendente.contains(tarefa)){
			tarefasPendente.set(tarefasPendente.indexOf(tarefa), tarefa);
		}else if(tarefasConferencia.contains(tarefa)){
			tarefasConferencia.set(tarefasConferencia.indexOf(tarefa), tarefa);
		}
	}
	
	public void update(final Sprint sprint){
		for(Tarefa t : tarefasAberta)
			if(t.getSprint().equals(sprint))
				t.setSprint(sprint);
		for(Tarefa t : tarefasPendente)
			if(t.getSprint().equals(sprint))
				t.setSprint(sprint);
		for(Tarefa t : tarefasConferencia)
			if(t.getSprint().equals(sprint))
				t.setSprint(sprint);
	}
	
	public List<Tarefa> getTarefasAberta() {
		return tarefasAberta;
	}
	
	public void setTarefasAberta(List<Tarefa> tarefasAberta) {
		this.tarefasAberta = tarefasAberta;
	}
	
	public List<Tarefa> getTarefasPendente() {
		return tarefasPendente;
	}
	
	public void setTarefasPendente(List<Tarefa> tarefasPendente) {
		this.tarefasPendente = tarefasPendente;
	}
	
	public List<Tarefa> getTarefasConferencia() {
		return tarefasConferencia;
	}
	
	public void setTarefasConferencia(List<Tarefa> tarefasConferencia) {
		this.tarefasConferencia = tarefasConferencia;
	}
	
	public boolean isPodeDelegar(Usuario usuario){
		for(Tarefa tarefa : tarefasPendente){
			if(usuario.equals(tarefa.getUsuario()))
				return false;
		}
		for(Tarefa tarefa : tarefasConferencia){
			if(usuario.equals(tarefa.getUsuario()))
				return false;
		}
		return true;
	}
	
	public void listAll(){
		System.out.println("Abertas: ");
		for(Tarefa t : tarefasAberta) 
			System.out.println(t.getCodigo());
		
		System.out.println("Pendentes: ");
		for(Tarefa t : tarefasPendente) 
			System.out.println(t.getCodigo());

		System.out.println("Conferencia: ");
		for(Tarefa t : tarefasConferencia) 
			System.out.println(t.getCodigo());
	}
		
}
